package fb

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"strings"
	"time"

	"main.go/minecraft"
	"main.go/minecraft/protocol/packet"
)

type Authenticator struct {
	Identify *Identify
	client   *Client
}

func responsePyRPC(conn *minecraft.Conn, pk *packet.PyRpc, client *Client) error {
	fmt.Printf("Authenticator-Intercept: Response netease PyRPC\n")
	if strings.Contains(string(pk.Content), "GetLoadingTime") {
		//fmt.Printf("GetLoadingTime!!\n")
		uid := conn.IdentityData().Uid
		num := uid&255 ^ (uid&65280)>>8
		curTime := time.Now().Unix()
		num = curTime&3 ^ (num&7)<<2 ^ (curTime&252)<<3 ^ (num&248)<<8
		numcont := make([]byte, 2)
		binary.BigEndian.PutUint16(numcont, uint16(num))
		err := conn.WritePacket(&packet.PyRpc{
			Content: []byte{0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x93, 0xc4, 0x12, 0x53, 0x65, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x4c, 0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x69, 0x6d, 0x65, 0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x91, 0xcd, numcont[0], numcont[1], 0xc0},
		})
		if err != nil {
			fmt.Printf("Authenticator-Intercept: On handling netease PyRPC, an error occour (Fail to Write Packet) (%v)\n", err)
			return err
		}

	} else if strings.Contains(string(pk.Content), "check_server_contain_pet") {
		//fmt.Printf("Checkpet!!\n")

		// Pet req
		/*conn.WritePacket(&packet.PyRpc {
			Content: bytes.Join([][]byte{[]byte{0x82,0xc4,0x8,0x5f,0x5f,0x74,0x79,0x70,0x65,0x5f,0x5f,0xc4,0x5,0x74,0x75,0x70,0x6c,0x65,0xc4,0x5,0x76,0x61,0x6c,0x75,0x65,0x93,0xc4,0xb,0x4d,0x6f,0x64,0x45,0x76,0x65,0x6e,0x74,0x43,0x32,0x53,0x82,0xc4,0x8,0x5f,0x5f,0x74,0x79,0x70,0x65,0x5f,0x5f,0xc4,0x5,0x74,0x75,0x70,0x6c,0x65,0xc4,0x5,0x76,0x61,0x6c,0x75,0x65,0x94,0xc4,0x9,0x4d,0x69,0x6e,0x65,0x63,0x72,0x61,0x66,0x74,0xc4,0x3,0x70,0x65,0x74,0xc4,0x12,0x73,0x75,0x6d,0x6d,0x6f,0x6e,0x5f,0x70,0x65,0x74,0x5f,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x87,0xc4,0x13,0x61,0x6c,0x6c,0x6f,0x77,0x5f,0x73,0x74,0x65,0x70,0x5f,0x6f,0x6e,0x5f,0x62,0x6c,0x6f,0x63,0x6b,0xc2,0xc4,0xb,0x61,0x76,0x6f,0x69,0x64,0x5f,0x6f,0x77,0x6e,0x65,0x72,0xc3,0xc4,0x7,0x73,0x6b,0x69,0x6e,0x5f,0x69,0x64,0xcd,0x27,0x11,0xc4,0x9,0x70,0x6c,0x61,0x79,0x65,0x72,0x5f,0x69,0x64,0xc4},
					[]byte{byte(len(runtimeid))},
						[]byte(runtimeid),
						[]byte{0xc4,0x6,0x70,0x65,0x74,0x5f,0x69,0x64,0x1,0xc4,0xa,0x6d,0x6f,0x64,0x65,0x6c,0x5f,0x6e,0x61,0x6d,0x65,0xc4,0x14,0x74,0x79,0x5f,0x79,0x75,0x61,0x6e,0x73,0x68,0x65,0x6e,0x67,0x68,0x75,0x6c,0x69,0x5f,0x30,0x5f,0x30,0xc4,0x4,0x6e,0x61,0x6d,0x65,0xc4,0xc,0xe6,0x88,0x91,0xe7,0x9a,0x84,0xe4,0xbc,0x99,0xe4,0xbc,0xb4,0xc0},
				},[]byte{}),
		})*/

	} else if strings.Contains(string(pk.Content), "summon_pet_response") {
		//fmt.Printf("Summonpetres\n")
		/*conn.WritePacket(&packet.PyRpc {
			Content: []byte{0x82,0xc4,0x8,0x5f,0x5f,0x74,0x79,0x70,0x65,0x5f,0x5f,0xc4,0x5,0x74,0x75,0x70,0x6c,0x65,0xc4,0x5,0x76,0x61,0x6c,0x75,0x65,0x93,0xc4,0x19,0x61,0x72,0x65,0x6e,0x61,0x47,0x61,0x6d,0x65,0x50,0x6c,0x61,0x79,0x65,0x72,0x46,0x69,0x6e,0x69,0x73,0x68,0x4c,0x6f,0x61,0x64,0x82,0xc4,0x8,0x5f,0x5f,0x74,0x79,0x70,0x65,0x5f,0x5f,0xc4,0x5,0x74,0x75,0x70,0x6c,0x65,0xc4,0x5,0x76,0x61,0x6c,0x75,0x65,0x90,0xc0},
		})
		conn.WritePacket(&packet.PyRpc {
			Content: bytes.Join([][]byte{[]byte{0x82,0xc4,0x8,0x5f,0x5f,0x74,0x79,0x70,0x65,0x5f,0x5f,0xc4,0x5,0x74,0x75,0x70,0x6c,0x65,0xc4,0x5,0x76,0x61,0x6c,0x75,0x65,0x93,0xc4,0xb,0x4d,0x6f,0x64,0x45,0x76,0x65,0x6e,0x74,0x43,0x32,0x53,0x82,0xc4,0x8,0x5f,0x5f,0x74,0x79,0x70,0x65,0x5f,0x5f,0xc4,0x5,0x74,0x75,0x70,0x6c,0x65,0xc4,0x5,0x76,0x61,0x6c,0x75,0x65,0x94,0xc4,0x9,0x4d,0x69,0x6e,0x65,0x63,0x72,0x61,0x66,0x74,0xc4,0xe,0x76,0x69,0x70,0x45,0x76,0x65,0x6e,0x74,0x53,0x79,0x73,0x74,0x65,0x6d,0xc4,0xc,0x50,0x6c,0x61,0x79,0x65,0x72,0x55,0x69,0x49,0x6e,0x69,0x74,0xc4},
					[]byte{byte(len(runtimeid))},
						[]byte(runtimeid),
						[]byte{0xc0},
					},[]byte{}),
		})*/
		/*conn.WritePacket(&packet.PyRpc {
			Content: []byte{0x82,0xc4,0x8,0x5f,0x5f,0x74,0x79,0x70,0x65,0x5f,0x5f,0xc4,0x5,0x74,0x75,0x70,0x6c,0x65,0xc4,0x5,0x76,0x61,0x6c,0x75,0x65,0x93,0xc4,0x1f,0x43,0x6c,0x69,0x65,0x6e,0x74,0x4c,0x6f,0x61,0x64,0x41,0x64,0x64,0x6f,0x6e,0x73,0x46,0x69,0x6e,0x69,0x73,0x68,0x65,0x64,0x46,0x72,0x6f,0x6d,0x47,0x61,0x63,0x82,0xc4,0x8,0x5f,0x5f,0x74,0x79,0x70,0x65,0x5f,0x5f,0xc4,0x5,0x74,0x75,0x70,0x6c,0x65,0xc4,0x5,0x76,0x61,0x6c,0x75,0x65,0x90,0xc0},
		})*/
	} else if strings.Contains(string(pk.Content), "GetStartType") {
		//fmt.Printf("GetStartType!!\n")
		encData := pk.Content[68 : len(pk.Content)-1]
		response, err := client.TransferData(string(encData), fmt.Sprintf("%d", conn.IdentityData().Uid))
		if err != nil {
			fmt.Println("Authenticator-Intercept: On handling netease PyRPC, an error occour (Client Fail to Transfer Data)")
			return err
		}
		err = conn.WritePacket(&packet.PyRpc{
			Content: bytes.Join([][]byte{[]byte{0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x93, 0xc4, 0xc, 0x53, 0x65, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x79, 0x70, 0x65, 0x82, 0xc4, 0x8, 0x5f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x5f, 0xc4, 0x5, 0x74, 0x75, 0x70, 0x6c, 0x65, 0xc4, 0x5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x91, 0xc4},
				[]byte{byte(len(response))},
				[]byte(response),
				[]byte{0xc0},
			}, []byte{}),
		})
		if err != nil {
			fmt.Printf("Authenticator-Intercept: On handling netease PyRPC, an error occour (Fail to Write Packet) (%v)", err)
			return err
		}
	}
	return nil
}

func (authenticator *Authenticator) Intercept(conn *minecraft.Conn, pk packet.Packet) (packet.Packet, error) {
	switch pk.(type) {
	case *packet.PyRpc:
		err := responsePyRPC(conn, pk.(*packet.PyRpc), authenticator.client)
		if err != nil {
			fmt.Printf("Authenticator-Intercept: When response to PyRPC, an error occour (%v)", err)
			return nil, err
		} else {
			return nil, nil
		}
	}
	return pk, nil
}

func (authenticator *Authenticator) GenerateToken() (*minecraft.LoginToken, error) {
	var err error
	if authenticator.client != nil {
		authenticator.client.Close()
	}
	authenticator.client, err = CreateClient()
	if err != nil {
		fmt.Printf("Authenticator-GenerateToken: Fail to pass fb auth (%v)\n", err)
		return nil, fmt.Errorf("Authenticator-GenerateToken: Fail to generate fb client (%v)", err)
	}
	return authenticator.client.authNetEase(authenticator.Identify)
}
